<template>
    <Teleport to="body">
        <Transition name="dialog">
            <div v-show="show" class="pe-dialog-shadow" :class="modalClass" @click="modelClose"
                :style="{ zIndex, backgroundColor: modal ? '' : 'transparent' }">
                <div class="pe-dialog"
                    :style="{ width: getWidth(), marginTop: top, transform: draggable ? `translate(${translateX}px, ${translateY}px)` : '' }"
                    @click.stop>
                    <div class="pe-dialog-header" :style="{ cursor: draggable ? 'move' : '' }" @mousemove="dialogDrag"
                        @mousedown="onMousedown" @mouseup="dragFlag = false">
                        <slot name="header">
                            <span class="pe-dialog-title">{{ title }}</span>
                        </slot>
                        <div class="pe-dialog-icon" v-if="showClose" @click.stop="close">
                            <Close />
                        </div>
                    </div>
                    <div class="pe-dialog-main" @click.stop>
                        <slot></slot>
                    </div>
                </div>
            </div>
        </Transition>
    </Teleport>
</template>

<script setup lang="ts">
import { inject, ref, watch } from "vue"
import Close from "../../icons/close.vue";

const show = defineModel<boolean>()

const zIndex = inject("pe-z-index", ref<number>(2000))

/**
 * @param title 弹出框标题
 * @param width 弹出框宽度
 * @param top 弹出框与屏幕顶部的距离
 * @param modalClass 遮罩的自定义类名
 * @param close-on-click-modal 是否可以通过点击 modal 关闭 Dialog
 * @param show-close 是否显示关闭按钮
 * @param modal 是否需要遮罩层
 * @param draggable 是否可拖拽
 */
interface Props {
    title?: string,
    width?: number | string,
    top?: string,
    modalClass?: string,
    closeOnClickModal?: boolean,
    showClose?: boolean,
    modal?: boolean,
    draggable?: boolean
}

const props = withDefaults(defineProps<Props>(), {
    title: "Title",
    width: "50%",
    top: "15vh",
    closeOnClickModal: true,
    showClose: true,
    modal: true,
    draggable: false
})

/**
 * open 开启的回调
 * close 关闭的回调
 */
const emits = defineEmits(["open", "close"])

// 拖拽函数
const dragFlag = ref<boolean>(false)
const translateX = ref<number>(0)
const translateY = ref<number>(0)
let oldClientX = 0
let oldClientY = 0
const dialogDrag = (event: MouseEvent) => {
    if (dragFlag.value && props.draggable) {
        // 获取新的鼠标坐标
        const clientX = event.clientX
        const clientY = event.clientY
        translateX.value = clientX - oldClientX + translateX.value
        translateY.value = clientY - oldClientY + translateY.value
        oldClientX = clientX
        oldClientY = clientY
    }
}

// 鼠标按下事件
const onMousedown = (event: MouseEvent) => {
    if (props.draggable) {
        // 获取鼠标点击坐标
        oldClientX = event.clientX
        oldClientY = event.clientY
        dragFlag.value = true
    }
}

watch(show, newShow => {
    if (newShow) {
        zIndex.value++
        emits("open")
    }
}, { immediate: true })

const getWidth = () => {
    let tempWidth
    if (typeof props.width === 'number') {
        tempWidth = props.width + "px"
    } else {
        tempWidth = props.width
    }
    return tempWidth
}

// 点击遮罩层关闭事件
const modelClose = () => {
    if (props.closeOnClickModal) {
        show.value = false
        emits("close")
    }
}

// 点击关闭按钮事件
const close = () => {
    show.value = false
    emits("close")
}
</script>

<script lang="ts">
export default {
    name: "pe-dialog"
}
</script>
